/*
 * Copyright (c) 2002-2006 Universidade Federal de Campina Grande
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 */

package org.dea.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.twmacinta.util.MD5InputStream;

/**
 * @author Alexandro de Souza Soares - alexandro@lsd.ufcg.edu.br
 * @author Eduardo Colaco - eduardo@lsd.ufcg.edu.br
 * @author Marcelo Iury - iury@lsd.ufcg.edu.br Description: TODO Description for
 *         FileCheckSummer.java
 * @version 1.0 Date: 14/02/2006 Copyright (c) 2002-2006 Universidade Federal de
 *          Campina Grande
 */
public class CheckSummer {

	public static final String MD5_ALGORITHM = "MD5";
	public static final String SHA_ALGORITHM = "SHA";

	private static final int DEFAULT_BUFFER_SIZE = 65536;


	/**
	 * Creates the checksum from a given file.
	 * 
	 * @param filename the file name.
	 * @return a byte array containing the file checksum.
	 * @throws IOException an IOException may be thrown.
	 * @throws NoSuchAlgorithmException a NoSuchAlgorithmException may be
	 *         thrown.
	 */
	public static byte[ ] createChecksum( String filename ) throws IOException {

		if ( !(new File( filename ).exists()) ) {
			throw new IOException( "Invalid file location" );
		}

		MD5InputStream in = new MD5InputStream( new BufferedInputStream( new FileInputStream( filename ) ) );
		try{
			byte[ ] buffer = new byte[ DEFAULT_BUFFER_SIZE ];
			while ((in.read(buffer)) != -1);
		}finally{
			in.close();
		}
		return in.hash();
	}
	


	public static String createStringChecksum( String filename ) throws IOException{

		return byteArrayToHexString( createChecksum( filename ) ); // TODO causes incompatibility with with old version
	}


	/**
	 * Outputs the specified file checksum to the given destination.
	 * 
	 * @param filename the file name.
	 * @param destination the destination file name.
	 * @return the file containing the checksum.
	 * @throws IOException an IOException may be thrown.
	 * @throws NoSuchAlgorithmException a NoSuchAlgorithmException may be
	 *         thrown.
	 */
	public static File writeChecksum( String filename, String destination ) throws IOException,
		NoSuchAlgorithmException {

		File file = new File( destination );
		BufferedOutputStream output = new BufferedOutputStream( new FileOutputStream( file ) );
		output.write( createChecksum( filename ) );
		return file;
	}


	public static DigestOutputStream getDigestOutputStream( OutputStream out ) throws NoSuchAlgorithmException {

		DigestOutputStream dOut = new DigestOutputStream( out, MessageDigest.getInstance( MD5_ALGORITHM ) );
		return dOut;
	}


	public DigestInputStream getDigestInputStream( InputStream in ) throws NoSuchAlgorithmException {

		DigestInputStream dIn = new DigestInputStream( in, MessageDigest.getInstance( MD5_ALGORITHM ) );
		return dIn;
	}



	public static String byteChecksumToHexString(byte[] checksum) {
		return byteArrayToHexString( checksum  );
	}
	
	public static String byteToHexString( byte b ) {
		// 1st~4th bit hex(most signif.) //5th~8th bit hex
		return (Integer.toHexString( b >> 4 & 0xF )) + (Integer.toHexString( b & 0xF ));
	}
	
	public static String byteArrayToHexString( byte[] b ) {
		StringBuffer name = new StringBuffer();
		for ( int i = 0; i < b.length; i++ ) {
			name.append( byteToHexString( b[i] ) );
		}
		return name.toString();
	}

}
